package com.ma.a05;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName A05Application3
 * @Author: mayongqiang
 * @DATE 2022/4/1 20:15
 * @Description: 工厂后处理器模拟实现@Bean
 */

public class A05Application3 {
    private static final Logger log = LoggerFactory.getLogger(A05Application3.class);

    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);

        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        // 拿到Config.class中被@Bean标注的信息
        MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/ma/a05/Config.class"));
        Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : methods) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();

            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
            if (initMethod.length() > 0) {
                builder.setInitMethodName(initMethod);
            }


            builder.setFactoryMethodOnBean(method.getMethodName(), "config");
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);

            AbstractBeanDefinition bd = builder.getBeanDefinition();
            context.getDefaultListableBeanFactory().registerBeanDefinition(method.getMethodName(), bd);

        }


        context.refresh();
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }


        context.close();
    }
}
